//-----------------------------------------------------------------------
// <copyright file="AzManTransportHelper.cs" company="Alan Rodrigues">
//     Copyright (c) Alan Rodrigues. All rights reserved.
// </copyright>
// <developed>Alan Rodrigues (operninha@gmail.com)</developed>
//-----------------------------------------------------------------------
 
//#region License Info

//*
//Copyright 2006 Joe Langley (EE 2006)

//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.

//--------------------------------

//You must not remove this License Info from your applications! 
//Please send all questions or updates to: joe_langley78@hotmail.com

//Joe Langley
//joe_langley78@hotmail.com

//LAST UPDATE: 9/05/2006

//EE 2006
//*/

//#endregion

//using System;
//using System.Collections;
//using System.DirectoryServices;
//using System.IO;
//using System.Reflection;
//using System.Text;
//using Microsoft.Interop.Security.AzRoles;
////use interop version created by Microsoft
////v. 1.2.0.0 used now after SP1 install

//namespace AuthorizationContext
//{
//    /// <summary>
//    ///	NOTE I HAVE LEFT IN TRY/CATCH JUST SO WE KNOW DOWN THE ROAD IN CASE ERROR HAPPENS
//    /// </summary>
//    public class AzManTransportHelper
//    {
//        #region Consts

//        private const int AZ_AZSTORE_FLAG_AUDIT_IS_CRITICAL = 8;
//        private const int AZ_AZSTORE_FLAG_BATCH_UPDATE = 4;
//        private const int AZ_AZSTORE_FLAG_CREATE = 1;
//        private const int AZ_AZSTORE_FLAG_MANAGE_STORE_ONLY = 2;

//        #endregion

//        #region Constructors

//        private AzManTransportHelper()
//        {
//        }

//        #endregion

//        #region Implementation - Public

//        /// <summary>
//        /// Copy store on url srcUrl to store on destUrl.
//        /// </summary>
//        /// <param name="srcUrl">Target store url.</param>
//        /// <param name="destUrl">Destination store url</param>
//        /// <param name="patchOnly">If True - only applications existing in both stores
//        ///  updated; if False - destination store applications removed and new added.
//        /// </param>
//        public static void CopyStore(string srcUrl, string destUrl, IEnumerable appsNames, bool patchOnly)
//        {
//            if (srcUrl == null || srcUrl.Length == 0)
//            {
//                throw new ArgumentNullException("srcUrl", "Source Url can not be null or empty");
//            }
//            if (destUrl == null || destUrl.Length == 0)
//            {
//                throw new ArgumentNullException("destUrl", "Destination Url can not be null or empty");
//            }

//            IAzAuthorizationStore srcStore = new AzAuthorizationStoreClass();
//            srcStore.Initialize(0, srcUrl, null);

//            IAzAuthorizationStore destStore = CopyStore(destUrl, srcStore);

//            UpdateApplicationGroups(srcStore.ApplicationGroups, destStore.ApplicationGroups,
//                                    typeof (IAzAuthorizationStore), destStore, patchOnly);

//            UpdateApplications(srcStore, ref destStore, destUrl, appsNames, patchOnly);
//        }

//        #endregion

//        #region Implementation - OperationCollection

//        /*private static void UpdateOperations(IAzOperations srcOperations, IAzOperations destOperations, Type objectInterface, object destObj)
//        {
//            ArrayList curOperations = new ArrayList(); 
//            foreach(IAzOperation destOperation in destOperations)
//            {
//                curOperations.Add(destOperation.Name);
//            }
//            foreach(string operationName in curOperations)
//            {
//                MethodInfo delMethod = objectInterface.GetMethod("DeleteOperation");
//                delMethod.Invoke(destObj, new object[]{operationName, null});
//            }
//            MethodInfo submitMethod = objectInterface.GetMethod("Submit");
//            submitMethod.Invoke(destObj, new object[]{0, null});
//            PropertyInfo operationsProp = objectInterface.GetProperty("OperationCollection");
//            destOperations = (IAzOperations)operationsProp.GetValue(destObj, null);
//            foreach(IAzOperation srcOperation in srcOperations)
//            {
//                if (curOperations.Contains(srcOperation.Name))
//                {
//                    curOperations.Remove(srcOperation.Name); 
//                }
//                UpdateOperation(objectInterface, destObj, destOperations, srcOperation);
//            }
//        }*/

//        private static void UpdateOperations(IAzOperations srcOperations, IAzOperations destOperations,
//                                             Type objectInterface, object destObj)
//        {
//            ArrayList curOperations = new ArrayList();

//            foreach (IAzOperation destOperation in destOperations)
//            {
//                curOperations.Add(destOperation.Name);
//            }

//            foreach (IAzOperation srcOperation in srcOperations)
//            {
//                if (curOperations.Contains(srcOperation.Name))
//                {
//                    curOperations.Remove(srcOperation.Name);
//                }
//                UpdateOperation(objectInterface, destObj, destOperations, srcOperation);
//            }

//            foreach (string operationName in curOperations)
//            {
//                MethodInfo addMethod = objectInterface.GetMethod("DeleteOperation");
//                addMethod.Invoke(destObj, new object[] {operationName, null});
//            }
//        }

//        private static IAzOperation UpdateOperation(Type objectInterface, object destObj, IAzOperations destOperations,
//                                                    IAzOperation srcOperation)
//        {
//            IAzOperation destOperation = null;
//            foreach (IAzOperation currentOperation in destOperations)
//            {
//                if (currentOperation.Name.Equals(srcOperation.Name))
//                {
//                    destOperation = currentOperation;
//                    break;
//                }
//            }

//            if (destOperation == null)
//            {
//                MethodInfo addMethod = objectInterface.GetMethod("CreateOperation");
//                destOperation = (IAzOperation) addMethod.Invoke(destObj, new object[] {srcOperation.Name, null});
//            }

//            SetIfNotEqual(srcOperation, destOperation, typeof (IAzOperation), "ApplicationData");
//            SetIfNotEqual(srcOperation, destOperation, typeof (IAzOperation), "Description");
//            SetIfNotEqual(srcOperation, destOperation, typeof (IAzOperation), "operationId");

//            destOperation.Submit(0, null);

//            return destOperation;
//        }

//        #endregion

//        #region Implementation - TaskCollection

//        private static void UpdateTasks(IAzTasks srcTasks, IAzTasks destTasks, Type objectInterface, object destObj)
//        {
//            ArrayList curTasks = new ArrayList();

//            foreach (IAzTask2 destTask in destTasks)
//            {
//                curTasks.Add(destTask.Name);
//            }

//            foreach (IAzTask2 srcTask in srcTasks)
//            {
//                if (curTasks.Contains(srcTask.Name))
//                {
//                    curTasks.Remove(srcTask.Name);
//                }
//                UpdateTask(objectInterface, destObj, destTasks, srcTask);
//            }

//            foreach (string name in curTasks)
//            {
//                MethodInfo addMethod = objectInterface.GetMethod("DeleteTask");
//                addMethod.Invoke(destObj, new object[] {name, null});
//            }

//            PropertyInfo tasksProperty = objectInterface.GetProperty("TaskCollection", typeof (IAzTasks));
//            tasksProperty = objectInterface.GetProperty("TaskCollection");
//            IAzTasks tasks = (IAzTasks) tasksProperty.GetValue(destObj, new object[] {});

//            ApplyTaskChildren(srcTasks, tasks);
//        }

//        private static IAzTask2 UpdateTask(Type objectInterface, object destObj, IAzTasks destTasks, IAzTask2 srcTask)
//        {
//            IAzTask2 destTask = null;
//            foreach (IAzTask2 currentTask in destTasks)
//            {
//                if (currentTask.Name.Equals(srcTask.Name))
//                {
//                    destTask = currentTask;
//                    break;
//                }
//            }

//            if (destTask == null)
//            {
//                MethodInfo addMethod = objectInterface.GetMethod("CreateTask");
//                destTask = (IAzTask2) addMethod.Invoke(destObj, new object[] {srcTask.Name, null});
//            }

//            SetIfNotEqual(srcTask, destTask, typeof (IAzTask2), "ApplicationData");
//            SetIfNotEqual(srcTask, destTask, typeof (IAzTask2), "BizRuleLanguage");
//            SetIfNotEqual(srcTask, destTask, typeof (IAzTask2), "BizRule");
//            SetIfNotEqual(srcTask, destTask, typeof (IAzTask2), "BizRuleImportedPath");
//            SetIfNotEqual(srcTask, destTask, typeof (IAzTask2), "Description");
//            SetIfNotEqual(srcTask, destTask, typeof (IAzTask2), "IsRoleDefinition");

//            SynchronizeCollections(srcTask.OperationCollection, destTask.OperationCollection, typeof (IAzTask2), destTask, "AddOperation",
//                                   "DeleteOperation");

//            destTask.Submit(0, null);

//            return destTask;
//        }

//        private static void ApplyTaskChildren(IAzTasks srcTasks, IAzTasks destTasks)
//        {
//            foreach (IAzTask2 srcTask in srcTasks)
//            {
//                IAzTask2 destTask = null;
//                foreach (IAzTask2 currentTask in destTasks)
//                {
//                    if (currentTask.Name.Equals(srcTask.Name))
//                    {
//                        destTask = currentTask;
//                        break;
//                    }
//                }

//                if (destTask != null)
//                {
//                    SynchronizeCollections(srcTask.TaskCollection, destTask.TaskCollection, typeof (IAzTask2), destTask, "AddTask",
//                                           "DeleteTask");
//                    destTask.Submit(0, null);
//                }
//            }
//        }

//        #endregion

//        #region Implementation - ScopeCollection

//        private static void UpdateScopes(IAzScopes srcScopes, IAzScopes destScopes, Type objectInterface, object destObj)
//        {
//            ArrayList curScopes = new ArrayList();

//            foreach (IAzScope destScope in destScopes)
//            {
//                curScopes.Add(destScope.Name);
//            }

//            foreach (IAzScope srcScope in srcScopes)
//            {
//                if (curScopes.Contains(srcScope.Name))
//                {
//                    curScopes.Remove(srcScope.Name);
//                }

//                UpdateScope(objectInterface, destObj, destScopes, srcScope);
//            }

//            foreach (string scopeName in curScopes)
//            {
//                MethodInfo addMethod = objectInterface.GetMethod("DeleteScope");
//                addMethod.Invoke(destObj, new object[] {scopeName, null});
//            }
//        }

//        private static IAzScope UpdateScope(Type objectInterface, object destObj, IAzScopes destScopes,
//                                            IAzScope srcScope)
//        {
//            IAzScope destScope = null;
//            foreach (IAzScope currentScope in destScopes)
//            {
//                if (currentScope.Name.Equals(srcScope.Name))
//                {
//                    destScope = currentScope;
//                    break;
//                }
//            }

//            if (destScope == null)
//            {
//                MethodInfo addMethod = objectInterface.GetMethod("CreateScope");
//                destScope = (IAzScope) addMethod.Invoke(destObj, new object[] {srcScope.Name, null});
//            }

//            SetIfNotEqual(srcScope, destScope, typeof (IAzScope), "ApplicationData");
//            SetIfNotEqual(srcScope, destScope, typeof (IAzScope), "Description");

//            destScope.Submit(0, null);

//            UpdateApplicationGroups(srcScope.ApplicationGroups, destScope.ApplicationGroups, typeof (IAzScope),
//                                    destScope, false);

//            UpdateTasks(srcScope.TaskCollection, destScope.TaskCollection, typeof (IAzScope), destScope);

//            UpdateRoles(srcScope.RoleCollection, destScope.RoleCollection, typeof (IAzScope), destScope);

//            return destScope;
//        }

//        #endregion

//        #region Implementation - RoleCollection

//        private static void UpdateRoles(IAzRoles srcRoles, IAzRoles destRoles, Type objectInterface, object destObj)
//        {
//            ArrayList curRoles = new ArrayList();

//            foreach (IAzRole destRole in destRoles)
//            {
//                curRoles.Add(destRole.Name);
//            }

//            foreach (IAzRole srcRole in srcRoles)
//            {
//                if (curRoles.Contains(srcRole.Name))
//                {
//                    curRoles.Remove(srcRole.Name);
//                }
//                UpdateRole(objectInterface, destObj, destRoles, srcRole);
//            }

//            foreach (string roleName in curRoles)
//            {
//                MethodInfo addMethod = objectInterface.GetMethod("DeleteRole");
//                addMethod.Invoke(destObj, new object[] {roleName, null});
//            }
//        }

//        private static IAzRole UpdateRole(Type objectInterface, object destObj, IAzRoles destRoles, IAzRole srcRole)
//        {
//            if (objectInterface == null)
//                throw new ArgumentNullException("objectInterface");
//            if (destObj == null)
//                throw new ArgumentNullException("destObj");
//            if (destRoles == null)
//                throw new ArgumentNullException("destRoles");
//            if (srcRole == null)
//                throw new ArgumentNullException("srcRole");
//            IAzRole destRole = null;
//            foreach (IAzRole currentRole in destRoles)
//            {
//                if (currentRole.Name.Equals(srcRole.Name))
//                {
//                    destRole = currentRole;
//                    break;
//                }
//            }
//            if (destRole == null)
//            {
//                MethodInfo addMethod = objectInterface.GetMethod("CreateRole");
//                destRole = (IAzRole) addMethod.Invoke(destObj, new object[] {srcRole.Name, null});
//            }
//            if (destRole == null)
//                throw new NullReferenceException("destRole is null");
//            SetIfNotEqual(srcRole, destRole, typeof (IAzRole), "ApplicationData");
//            SetIfNotEqual(srcRole, destRole, typeof (IAzRole), "Description");
//            try
//            {
//                SynchronizeCollections(srcRole.Members, destRole.Members, typeof (IAzRole), destRole, "AddMember",
//                                       "DeleteMember");
//            }
//            catch (Exception innerException)
//            {
//                throw new Exception("failure on Members", innerException);
//            }
//            try
//            {
//                SynchronizeCollections(srcRole.AppMembers, destRole.AppMembers, typeof (IAzRole), destRole,
//                                       "AddAppMember", "DeleteAppMember");
//            }
//            catch (Exception innerException)
//            {
//                throw new Exception("failure on Members", innerException);
//            }
//            try
//            {
//                SynchronizeCollections(srcRole.OperationCollection, destRole.OperationCollection, typeof (IAzRole), destRole,
//                                       "AddOperation", "DeleteOperation");
//            }
//            catch (Exception innerException)
//            {
//                throw new Exception("failure on OperationCollection", innerException);
//            }
//            try
//            {
//                SynchronizeCollections(srcRole.TaskCollection, destRole.TaskCollection, typeof (IAzRole), destRole, "AddTask",
//                                       "DeleteTask");
//            }
//            catch (Exception innerException)
//            {
//                throw new Exception("failure on TaskCollection", innerException);
//            }

//            try
//            {
//                destRole.Submit(0, null);
//            }
//            catch (Exception innerException)
//            {
//                throw new Exception("failure on Submit", innerException);
//            }
//            return destRole;
//        }

//        #endregion

//        #region Implementation - ApplicationCollection

//        private static void UpdateApplications(IAzAuthorizationStore srcStore, ref IAzAuthorizationStore destStore,
//                                               string destUrl, IEnumerable appsNames, bool patchOnly)
//        {
//            Hashtable tobeCopied = new Hashtable(
//                new CaseInsensitiveHashCodeProvider(), new CaseInsensitiveComparer());
//            foreach (string appName in appsNames)
//            {
//                tobeCopied.Add(appName, null);
//            }
//            ArrayList curApplications = new ArrayList();

//            foreach (IAzApplication destApplication in destStore.ApplicationCollection)
//            {
//                curApplications.Add(destApplication.Name);
//            }
//            foreach (IAzApplication srcApplication in srcStore.ApplicationCollection)
//            {
//                if (tobeCopied.Contains(srcApplication.Name) == false)
//                {
//                    continue;
//                }
//                if (curApplications.Contains(srcApplication.Name))
//                {
//                    curApplications.Remove(srcApplication.Name);
//                }
//                // Remove applicationName and reopen store
//                foreach (IAzApplication currentApplication in destStore.ApplicationCollection)
//                {
//                    if (currentApplication.Name.Equals(srcApplication.Name))
//                    {
//                        destStore.DeleteApplication(srcApplication.Name, null);
//                        // We have to reopen the store due to the bug in AzMan implementation.
//                        // At least for now I have not found a way to avoid this.
//                        destStore.Submit(0, null);
//                        destStore = OpenStore(destUrl);
//                        break;
//                    }
//                }
//                UpdateApplication(destStore, srcApplication);
//            }
//            if (patchOnly == false)
//            {
//                foreach (string applicationName in curApplications)
//                {
//                    destStore.DeleteApplication(applicationName, null);
//                }
//            }
//        }

//        private static IAzApplication UpdateApplication(IAzAuthorizationStore destStore, IAzApplication srcApplication)
//        {
//            IAzApplication destApplication = null;
//            foreach (IAzApplication currentApplication in destStore.ApplicationCollection)
//            {
//                if (currentApplication.Name.Equals(srcApplication.Name))
//                {
//                    destApplication = currentApplication;
//                    break;
//                }
//            }

//            if (destApplication == null)
//            {
//                destApplication = destStore.CreateApplication(srcApplication.Name, null);
//            }

//            SetIfNotEqual(srcApplication, destApplication, typeof (IAzApplication), "ApplicationData");
//            SetIfNotEqual(srcApplication, destApplication, typeof (IAzApplication), "AuthzInterfaceClsid");
//            SetIfNotEqual(srcApplication, destApplication, typeof (IAzApplication), "Description");
//            //SetIfNotEqual(srcApplication, destApplication, typeof(IAzApplication), "ApplyStoreSacl");
//            //SetIfNotEqual(srcApplication, destApplication, typeof(IAzApplication), "GenerateAudits");

//            destApplication.Submit(0, null);

//            UpdateApplicationGroups(srcApplication.ApplicationGroups, destApplication.ApplicationGroups,
//                                    typeof (IAzApplication), destApplication, false);

//            UpdateOperations(srcApplication.OperationCollection, destApplication.OperationCollection, typeof (IAzApplication),
//                             destApplication);

//            UpdateTasks(srcApplication.TaskCollection, destApplication.TaskCollection, typeof (IAzApplication), destApplication);

//            UpdateRoles(srcApplication.RoleCollection, destApplication.RoleCollection, typeof (IAzApplication), destApplication);

//            UpdateScopes(srcApplication.ScopeCollection, destApplication.ScopeCollection, typeof (IAzApplication), destApplication);

//            return destApplication;
//        }

//        #endregion

//        #region Implementation - Application Groups

//        private static void UpdateApplicationGroups(IAzApplicationGroups srcGrpoups, IAzApplicationGroups destGroups,
//                                                    Type objectInterface, object destObj, bool patchOnly)
//        {
//            ArrayList curApplicationGroups = new ArrayList();

//            foreach (IAzApplicationGroup destApplicationGroup in destGroups)
//            {
//                curApplicationGroups.Add(destApplicationGroup.Name);
//            }

//            foreach (IAzApplicationGroup srcApplicationGroup in srcGrpoups)
//            {
//                if (curApplicationGroups.Contains(srcApplicationGroup.Name))
//                {
//                    curApplicationGroups.Remove(srcApplicationGroup.Name);
//                }
//                UpdateApplicationGroup(objectInterface, destObj, destGroups, srcApplicationGroup);
//            }

//            if (patchOnly == false)
//            {
//                foreach (string groupName in curApplicationGroups)
//                {
//                    MethodInfo addMethod = objectInterface.GetMethod("DeleteApplicationGroup");
//                    addMethod.Invoke(destObj, new object[] {groupName, null});
//                }
//            }

//            PropertyInfo applicationGroupsProperty =
//                objectInterface.GetProperty("ApplicationGroups", typeof (IAzApplicationGroups));
//            applicationGroupsProperty = objectInterface.GetProperty("ApplicationGroups");
//            IAzApplicationGroups groups = (IAzApplicationGroups)
//                                          applicationGroupsProperty.GetValue(destObj, new object[] {});

//            ApplyApplicationGroupChildren(srcGrpoups, groups);
//        }

//        private static IAzApplicationGroup UpdateApplicationGroup(Type objectInterface, object destObj,
//                                                                  IAzApplicationGroups destGroups,
//                                                                  IAzApplicationGroup srcApplicationGroup)
//        {
//            IAzApplicationGroup destApplicationGroup = null;
//            foreach (IAzApplicationGroup currentApplicationGroup in destGroups)
//            {
//                if (currentApplicationGroup.Name.Equals(srcApplicationGroup.Name))
//                {
//                    destApplicationGroup = currentApplicationGroup;
//                    break;
//                }
//            }

//            if (destApplicationGroup == null)
//            {
//                MethodInfo addMethod = objectInterface.GetMethod("CreateApplicationGroup");
//                destApplicationGroup =
//                    (IAzApplicationGroup) addMethod.Invoke(destObj, new object[] {srcApplicationGroup.Name, null});
//            }

//            SetIfNotEqual(srcApplicationGroup, destApplicationGroup, typeof (IAzApplicationGroup), "Description");
//            SetIfNotEqual(srcApplicationGroup, destApplicationGroup, typeof (IAzApplicationGroup), "LdapQuery");
//            SetIfNotEqual(srcApplicationGroup, destApplicationGroup, typeof (IAzApplicationGroup), "Type");

//            SynchronizeCollections(
//                srcApplicationGroup.Members,
//                destApplicationGroup.Members,
//                typeof (IAzApplicationGroup), destApplicationGroup, "AddMember", "DeleteMember"
//                );

//            SynchronizeCollections(
//                srcApplicationGroup.NonMembers,
//                destApplicationGroup.NonMembers,
//                typeof (IAzApplicationGroup), destApplicationGroup, "AddNonMember", "DeleteNonMember"
//                );

//            destApplicationGroup.Submit(0, null);

//            return destApplicationGroup;
//        }

//        private static void ApplyApplicationGroupChildren(IAzApplicationGroups srcGroups,
//                                                          IAzApplicationGroups destGroups)
//        {
//            foreach (IAzApplicationGroup srcApplicationGroup in srcGroups)
//            {
//                IAzApplicationGroup destApplicationGroup = null;
//                foreach (IAzApplicationGroup currentApplicationGroup in destGroups)
//                {
//                    if (currentApplicationGroup.Name.Equals(srcApplicationGroup.Name))
//                    {
//                        destApplicationGroup = currentApplicationGroup;
//                        break;
//                    }
//                }

//                if (destApplicationGroup != null)
//                {
//                    SynchronizeCollections(
//                        srcApplicationGroup.AppMembers,
//                        destApplicationGroup.AppMembers,
//                        typeof (IAzApplicationGroup), destApplicationGroup, "AddAppMember", "DeleteAppMember"
//                        );

//                    SynchronizeCollections(
//                        srcApplicationGroup.AppNonMembers,
//                        destApplicationGroup.AppNonMembers,
//                        typeof (IAzApplicationGroup), destApplicationGroup, "AddAppNonMember", "DeleteAppNonMember"
//                        );

//                    destApplicationGroup.Submit(0, null);
//                }
//            }
//        }

//        #endregion

//        #region Implementation - Store

//        private static IAzAuthorizationStore CopyStore(string destUrl, IAzAuthorizationStore srcStore)
//        {
//            IAzAuthorizationStore destStore = new AzAuthorizationStoreClass();

//            //if (IsStoreExists(destUrl))
//            //{
//            try
//            {
//                destStore.Initialize(AZ_AZSTORE_FLAG_BATCH_UPDATE, destUrl, null);
//            }
//            catch
//            {
//                destStore.Initialize(1, destUrl, null);
//            }
//            //	}
//            //	else
//            //	{
//            //		destStore.Initialize(1, destUrl, null);
//            //	}

//            SetIfNotEqual(srcStore, destStore, typeof (IAzAuthorizationStore), "ApplicationData");
//            SetIfNotEqual(srcStore, destStore, typeof (IAzAuthorizationStore), "Description");
//            SetIfNotEqual(srcStore, destStore, typeof (IAzAuthorizationStore), "DomainTimeout");
//            SetIfNotEqual(srcStore, destStore, typeof (IAzAuthorizationStore), "MaxScriptEngines");
//            //SetIfNotEqual(srcStore, destStore, typeof(IAzAuthorizationStore), "ApplyStoreSacl");
//            //SetIfNotEqual(srcStore, destStore, typeof(IAzAuthorizationStore), "GenerateAudits");

//            //Policy administrators
//            SynchronizeCollections(
//                (ICollection) srcStore.PolicyAdministrators,
//                (ICollection) destStore.PolicyAdministrators,
//                destStore.GetType(), destStore, "AddPolicyAdministrator", "DeletePolicyAdministrator"
//                );

//            //Policy readers.
//            SynchronizeCollections(
//                (ICollection) srcStore.PolicyReaders,
//                (ICollection) destStore.PolicyReaders,
//                destStore.GetType(), destStore, "AddPolicyReader", "DeletePolicyReader"
//                );

//            destStore.Submit(0, null);

//            return destStore;
//        }

//        /// <summary>
//        /// Return true if store exists.		
//        /// </summary>
//        /// <param name="storeUrl">Store URL.</param>
//        /// <returns>True if store exists</returns>
//        public static bool IsStoreExists(string storeUrl)
//        {
//            string storeType = string.Empty;
//            string pathToStore = storeUrl;
//            int i = pathToStore.IndexOf("//") + 2;
//            if (i < pathToStore.Length)
//            {
//                storeType = pathToStore.Substring(0, i);
//                pathToStore = pathToStore.Substring(i);
//            }

//            switch (storeType)
//            {
//                case "msldap://":
//                    return IsLdapObjectExists(pathToStore);

//                case "msxml://":
//                    return File.Exists(pathToStore);

//                default:
//                    throw new ArgumentException(
//                        "Store URL must be in form 'msxml://<PathToTheFile>' or 'msldap://<CN=StoreName,CN=ProgramName,DC=DomainName,DC=com>'.",
//                        "storeUrl");
//            }
//        }

//        private static bool IsLdapObjectExists(string ldapURL)
//        {
//            if (ldapURL.StartsWith("LDAP"))
//            {
//                throw new ArgumentException("ldapURL url must be without prefix LDAP://", "ldapURL");
//            }
//            string[] urlParts = ldapURL.Split(',');
//            StringBuilder rootUrl = new StringBuilder();
//            StringBuilder filterUrl = new StringBuilder();
//            foreach (string urlPart in urlParts)
//            {
//                if (!urlPart.StartsWith("CN"))
//                {
//                    rootUrl.AppendFormat(",{0}", urlPart);
//                }
//                else
//                {
//                    filterUrl.AppendFormat(",{0}", urlPart);
//                }
//            }

//            if (rootUrl.Length > 0)
//            {
//                rootUrl.Remove(0, 1);
//            }

//            rootUrl.Insert(0, "LDAP://");

//            Console.WriteLine(rootUrl);

//            if (filterUrl.Length > 0)
//            {
//                filterUrl.Remove(0, 1);
//            }

//            Console.WriteLine(filterUrl);

//            DirectoryEntry entry = new DirectoryEntry(rootUrl.ToString());
//            DirectorySearcher searcher = new DirectorySearcher(entry);
//            searcher.Filter = filterUrl.ToString();
//            return (searcher.FindAll().Count > 0);
//        }

//        #endregion

//        #region Implementation - Utils

//        private static void SynchronizeCollections(object srcCollection, object destCollection, Type objectInterface,
//                                                   object destObj, string addMethodName, string removeMethodName)
//        {
//            if (srcCollection == null)
//                throw new ArgumentNullException("srcCollection");
//            if (destCollection == null)
//                throw new ArgumentNullException("destCollection");
//            if (addMethodName == null)
//                throw new ArgumentNullException("addMethodName");
//            if (removeMethodName == null)
//                throw new ArgumentNullException("removeMethodName");

//            ArrayList destItems = new ArrayList((ICollection) destCollection);
//            if (destItems == null)
//                throw new NullReferenceException("destItems is null");
//            if (((ICollection) srcCollection) == null)
//                throw new NullReferenceException("srcCollection is null");
//            foreach (string item in (ICollection) srcCollection)
//            {
//                if (!destItems.Contains(item))
//                {
//                    MethodInfo addMethod = objectInterface.GetMethod(addMethodName);
//                    if (addMethod == null)
//                        throw new NullReferenceException("addMethod is null");
//                    addMethod.Invoke(destObj, new object[] {item, null});
//                }
//                else
//                {
//                    destItems.Remove(item);
//                }
//            }
//            foreach (string item in destItems)
//            {
//                MethodInfo removeMethod = objectInterface.GetMethod(removeMethodName);
//                if (removeMethod == null)
//                    throw new NullReferenceException("removeMethod is null");
//                removeMethod.Invoke(destObj, new object[] {item, null});
//            }
//        }

//        private static void SetIfNotEqual(object srcObject, object destObject, Type objectInterface, string propertyName)
//        {
//            PropertyInfo property = objectInterface.GetProperty(propertyName);
//            object val = property.GetValue(srcObject, null);
//            if (!val.Equals(property.GetValue(destObject, null)))
//            {
//                property.SetValue(destObject, val, null);
//            }
//        }

//        #endregion

//        #region Implementation - Store

//        private static IAzAuthorizationStore OpenStore(string sUrl)
//        {
//            IAzAuthorizationStore store = new AzAuthorizationStoreClass();

//            try
//            {
//                store.Initialize(AZ_AZSTORE_FLAG_BATCH_UPDATE, sUrl, null);
//            }
//            catch
//            {
//                store.Initialize(1, sUrl, null);
//            }

//            return store;
//        }

//        #endregion

//        public static IEnumerable GetApplicationsNames(string srcUrl)
//        {
//            if (srcUrl == null || srcUrl.Length == 0)
//            {
//                throw new ArgumentNullException("srcUrl", "Source Url can not be null or empty");
//            }

//            IAzAuthorizationStore srcStore = new AzAuthorizationStoreClass();
//            srcStore.Initialize(0, srcUrl, null);

//            ArrayList applications = new ArrayList();
//            foreach (IAzApplication srcApplication in srcStore.ApplicationCollection)
//            {
//                applications.Add(srcApplication.Name);
//            }
//            return applications;
//        }
//    }
//}